﻿using Mirror;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Driver : NetworkBehaviour
{
    public enum DriveLevel
    {
        LEVEL_AP,
        LEVEL_A,
        LEVEL_B,
        LEVEL_C,
        LEVEL_D,
        LEVEL_NULL,
    }
    public enum LicenseEvaluate
    {
        NOT_PASS,
        PASS,
        NIU_BI,
    }
    public enum State
    {
        STATE_STANDBY,      //  待机
        STATE_CHASE,        //  追击
        STATE_MOVE,         //  移动
        STATE_PATROL,       //  巡逻
        STATE_RETREAT,      //  撤退
        STATE_FIGHT,        //  交战
        STATE_HARASS,       //  骚扰
        STATE_ENCIRCLE,     //  环绕
        STATE_FOLLOW,       //  跟随
        STATE_VANGUARD,     //  前锋
    }; 
    public float KeepDistance =0;
    public float MaxDistance = -1;
    public float MinDistance = -1;
    public float ReactionSpeed = 0.5f;
    public State m_CurrentState = State.STATE_STANDBY;
    public Team Team = null;
    public bool isDebug = false;
    public bool m_IsManual = false;
    public bool m_DareToDie = false;
    public bool m_Exercise = false;


    public Vector3 FixedPartoleP1;
    public Vector3 FixedPartoleP2;
    public List<Vector3> PartolePath;
    public int m_PartoleProcess=0;

    float m_SupportTimeRangeMax = 10;
    float m_SupportTimeRangeMin = 5;
    float m_SupportTimeMax = 10;
    float m_SupportTimeCount = 0;
    float m_BackAngle = 120;

    float m_ElectricWeight = 0.5f;
    public GameObject Target
    {
        set {
            m_Target = value;

            if (m_Exercise == false)
                m_CurrentState = State.STATE_FIGHT;
        }
        get { return m_Target; }
    }
    public Vector3 m_TargetPosition;
    Ship m_Ship;

    float m_CheckInterval = 1;
    float m_CheckTimeCount=0;
    GameObject m_Target;
    public GameObject m_FollowTarget;
    public GameObject m_VanguardTarget;
    private void Awake()
    {
        if (FixedPartoleP1.x != 0 && FixedPartoleP1.y != 0 )
            PartolePath.Add(FixedPartoleP1);
        if (FixedPartoleP2.x != 0 && FixedPartoleP2.y != 0 )
            PartolePath.Add(FixedPartoleP2);

        m_BackAngle = Random.Range(60, 120);
    }
    void Start()
    {
        m_CheckInterval = Random.Range(1, 3);
    }

    // Update is called once per frame
    void Update()
    {
        m_Ship = GetComponent<Ship>();
        if (!m_Ship)
            return;
        CheckTarget();
        if (m_IsManual)
            return;
        if (UtilsGame.IsOnline() && !UtilsGame.IsServer(gameObject))
        {
            return;
        }



        //  
        if (m_Target)
        {
            m_TargetPosition = Target.transform.position;
        }
        else if(m_FollowTarget)
        {
            m_TargetPosition = m_FollowTarget.transform.position;
            m_CurrentState = State.STATE_FOLLOW;
        }
        else if(m_VanguardTarget)
        {
            Vector3 offset = new Vector3();
            var ship = m_VanguardTarget.GetComponent<Ship>();
            if(ship)
                offset = ship.transform.up * 9;

            m_TargetPosition = m_VanguardTarget.transform.position + offset ;
            m_CurrentState = State.STATE_VANGUARD;
        }
        else if(m_CurrentState == State.STATE_FIGHT ||
            m_CurrentState == State.STATE_CHASE)
        {
            m_CurrentState = State.STATE_STANDBY;
        }

        // 如果不能动就转圈圈
        if (m_Ship.m_ShipStruct.VelocityMax == 0)
        {
            m_Ship.rotationLeft();
            return;
        }

        switch (m_CurrentState)
        {
        case State.STATE_CHASE:
                chase();
                break;
        case State.STATE_ENCIRCLE:
                encircle();
                break;
        case State.STATE_HARASS:
                harass();
                break;
        case State.STATE_MOVE:
                move();
                break;
        case State.STATE_PATROL:
                patrol();
                break;
        case State.STATE_RETREAT:
                retereat();
                break;
        case State.STATE_FIGHT:
                fight();
                break;
        case State.STATE_STANDBY:
                standby();
                break;
        case State.STATE_FOLLOW:
                follow();
                break;
            case State.STATE_VANGUARD:
                vanguard();
                break;
        }
        //  看情况开启或关闭偏射盾
        if (!m_IsManual)
        {
            m_Ship.SetFeatureSwitch(true);
        }
        else
        {
            m_Ship.SetFeatureSwitch(false);
        }
    }

    private void FixedUpdate()
    {
        if (!m_Ship)
            return;
        if (UtilsGame.IsOnline() && !UtilsGame.IsServer(gameObject))
        {
            return;
        }


        checkShip();

    }

    public float currentTime = 0;
    public float findTargetTime = 0.1f;
    public void CheckTarget() 
    {
        if (UtilsGame.IsOnline() && !UtilsGame.IsServer(gameObject) &&
            GetComponent<PlayerNetwork>() == null)
            return;

        currentTime += Time.deltaTime;
        if (currentTime < findTargetTime)
            return;
        currentTime = 0;
        findTargetTime = Random.Range(0.1f, ReactionSpeed);

        //  检测飞行道具，如果在附近则攻击
        var itemTargetList = FlyItemManager.Instance.checkFlyItemsInRange(transform.position, (MinDistance +MaxDistance)/2, m_Ship.m_ShipStruct.Influence);
        if (null != itemTargetList)
            m_Ship.SmashTarget(itemTargetList);


        //   如果检测到敌方在自己的攻击范围内，则切换目标
        var selfInfluence = m_Ship.m_ShipStruct.Influence;
        float checkRange = m_Ship.m_ShipStruct.DetectRange;
        List<ArmTarget> targets = ShipManager.Instance.CheckShipInRange(m_Ship.transform.position, checkRange, m_Ship.m_ShipStruct.Influence);

        if (null != targets)
        {
            m_Ship.SmashTarget(targets, false);

            var nearTarget = findMostNearShip(targets);
            if (nearTarget != null && nearTarget.Target.GetComponent<Ship>())
            {

                Ship nearShip = nearTarget.Target.GetComponent<Ship>();

                float fightingCapacityScale = checkFightingCapacityScale(nearShip);
                if ((fightingCapacityScale < 3 && m_CurrentState != State.STATE_CHASE) || 
                    (Target == null && m_FollowTarget == null && m_VanguardTarget == null))
                {
                    if(transform.parent)
                    {
                        Headquarters headquarters = transform.parent.GetComponent<Headquarters>();
                        if (headquarters)
                        {
                            headquarters.FoundTarget(nearShip.gameObject);
                        }
                    }
                    Target = nearShip.gameObject;
                }
            }
        }
    }

    public static ArmTarget findMostNearShip(List<ArmTarget> targets)
    {
        if (targets.Count <= 0)
            return null;
        float minDistance = 10000000000000;
        Ship nearShip = null;
        ArmTarget nearTarget = new ArmTarget();
        foreach (var target in targets)
        {
            if(target.Type != ArmTarget.TargetType.SHIP)
            {
                continue;
            }
            Ship targetShip = target.Target.GetComponent<Ship>();
            if(targetShip &&
                target.Distance < minDistance )
            {
                minDistance = target.Distance;
                nearShip = targetShip;
            }
        }
        nearTarget.Target = nearShip.gameObject;
        nearTarget.Distance = minDistance;
        return nearTarget ;
    }
    

    void vanguard()
    {
        if (m_VanguardTarget == null)
            return;

        var ship = GetComponent<Ship>();
        if (!ship)
            return;
        KeepDistance = 0.5f;
        m_Ship.Focus(m_TargetPosition);

        var defference = m_TargetPosition - m_Ship.transform.position;
        if (defference.magnitude < KeepDistance)
        {
            m_Ship.moveBack();
        }
        else
        {
            m_Ship.moveForward();
        }
    }
    void follow()
    {
        if (m_FollowTarget == null)
            return;

        var ship = GetComponent<Ship>();
        if (!ship)
            return;
        KeepDistance = (MinDistance + MaxDistance) / 2;
        if (m_DareToDie)
            KeepDistance = 2;
        m_Ship.Focus(m_TargetPosition);

        var defference = m_TargetPosition - m_Ship.transform.position;
        if (defference.magnitude < KeepDistance)
        {
            m_Ship.moveBack();
        }
        else
        {
            m_Ship.moveForward();
        }
    }
    void standby()
    {
        if (!m_Ship)
            return;
        //var selfInfluence = m_Ship.m_ShipStruct.Influence;
        //var nearObj = checkShipInRange(MinDistance, selfInfluence);
        //if (nearObj)
        //{
        //    Target = nearObj.gameObject;
        //    m_Ship.Focus(m_TargetPosition);
        //}

    }

    void chase()
    {
        move();

        if (!m_Target)
        {
            return;
        }
        m_Ship.OnChase();
        //  如果发现打不过了
        Ship targetShip = m_Target.GetComponent<Ship>();
        if (targetShip)
        {
            if (CalcFightCapacityWeight(m_Ship, targetShip) < 0.3f ||
                (m_TargetPosition - transform.position).magnitude > MaxDistance)
            {
                m_CurrentState = State.STATE_FIGHT;
            }
        }
    }
    void move()
    {
        var ship = GetComponent<Ship>();
        if (!ship)
            return;
        m_Ship.Focus(m_TargetPosition);
        forward();
    }
    void patrol()
    {
        var ship = GetComponent<Ship>();
        if (!ship)
            return;
        if(PartolePath.Count > 1)
        {
            var deffence = PartolePath[m_PartoleProcess] - transform.position;
            if (deffence.magnitude < 1)
            {
                m_PartoleProcess++;
                if (m_PartoleProcess >= PartolePath.Count)
                {
                    m_PartoleProcess = 0;
                }
            }

            m_TargetPosition = PartolePath[m_PartoleProcess];
            move();
        }
    }

    void fight()
    {
        var ship = GetComponent<Ship>();
        if (!ship)
            return;
        m_Ship.OnFight();
        KeepDistance = MinDistance;
        m_Ship.Focus(m_TargetPosition);

        var defference = m_TargetPosition - m_Ship.transform.position;
        if (defference.magnitude < KeepDistance)
        {
            m_Ship.moveBack();
        }
        else
        {
            m_Ship.moveForward();
        }
        if (!m_Target)
            return;
        Ship targetShip = m_Target.GetComponent<Ship>();
        if (targetShip)
        {
            //  如果敌方状态不好，就追击
            float fightCapacityWeight = CalcFightCapacityWeight(m_Ship, targetShip);
            if (fightCapacityWeight > 0.7f)
            {
                m_CurrentState = State.STATE_CHASE;
            }

            //  如果自己状态不好，就骚扰
            if (fightCapacityWeight < 0.3f ||
                targetShip.FightingCapacity > m_Ship.FightingCapacity * 1.5)
            {
                m_CurrentState = State.STATE_HARASS;
            }
        }
    }

    float CalcFightCapacityWeight(Ship selfShip, Ship targetShip)
    {

        float enemyElectricScale = (targetShip.m_ShipStruct.Electric / targetShip.m_ShipStruct.m_ElectricMax) * m_ElectricWeight;
        float enemyStructScale = (targetShip.m_ShipStruct.StructurePoint / targetShip.m_ShipStruct.StructurePointMax);

        float selfElectricScale = (m_Ship.m_ShipStruct.Electric / m_Ship.m_ShipStruct.m_ElectricMax) * m_ElectricWeight;
        float selfStructScale = (m_Ship.m_ShipStruct.StructurePoint / m_Ship.m_ShipStruct.StructurePointMax);

        float enemyWeight = enemyElectricScale + enemyStructScale;
        float selfWeight = selfElectricScale + selfStructScale;
        return selfWeight / (selfWeight + enemyWeight);
    }
    void harass()
    {
        var ship = GetComponent<Ship>();
        if (!ship)
            return;

        // 保持距离并且绕到他屁股后面
        KeepDistance = MinDistance;
        m_Ship.Focus(m_TargetPosition);

        var defference = m_TargetPosition - m_Ship.transform.position;
        if (defference.magnitude < KeepDistance)
            m_Ship.moveBack();
        else
            m_Ship.moveForward();

        if(m_Target)
        {
            Ship targetShip = m_Target.GetComponent<Ship>();
            if (targetShip)
            {
                var relativeDir = Vector3.Normalize(m_Ship.transform.position - m_TargetPosition);
                if (Vector3.Angle(relativeDir, targetShip.transform.up) < m_BackAngle)
                {
                    if (Vector3.Cross(relativeDir, targetShip.transform.up).z >= 0)
                        m_Ship.moveLeft();
                    else
                        m_Ship.moveRight();
                }
            }

            //  状态不好就撤退
            float fightCapacityWeight = CalcFightCapacityWeight(m_Ship, targetShip);
            if (fightCapacityWeight < 0.3f ||
                m_Ship.m_ShipStruct.Electric < m_Ship.m_ShipStruct.m_ElectricMax / 5)
            {
                if(!m_DareToDie)
                    m_CurrentState = State.STATE_RETREAT;
            }
        }

        //  请求支援
        m_SupportTimeCount += Time.deltaTime;
        if(m_SupportTimeCount > m_SupportTimeMax)
        {
            m_SupportTimeMax = UnityEngine.Random.Range(m_SupportTimeRangeMin, m_SupportTimeRangeMax);
            m_SupportTimeCount = 0;
            requstSupport();
        }
    }
    void retereat()
    {
        var ship = GetComponent<Ship>();
        if (!ship)
            return;

        m_Ship.OnRetreat();
        //  后退
        var defference = m_TargetPosition - m_Ship.transform.position;
        if (defference.magnitude < m_Ship.m_ShipStruct.m_DetectRange)
        {
            m_Ship.moveBack();
            m_Ship.Focus(m_TargetPosition);
        }

        // 如果状态好了就迎战
        if (m_Ship.m_ShipStruct.StructurePoint > m_Ship.m_ShipStruct.StructurePointMax * 0.5||
            m_Ship.m_ShipStruct.Electric > m_Ship.m_ShipStruct.m_ElectricMax * 0.5)
        {
            m_CurrentState = State.STATE_FIGHT;
        }

        //  请求支援
        m_SupportTimeCount += Time.deltaTime;
        if (m_SupportTimeCount > m_SupportTimeMax)
        {
            m_SupportTimeMax = UnityEngine.Random.Range(m_SupportTimeRangeMin, m_SupportTimeRangeMax);
            m_SupportTimeCount = 0;
            requstSupport();
        }
    }
    void encircle()
    {

    }


    void forward()
    {
        var targetDifference = m_TargetPosition - transform.position;
        var targetDir = targetDifference.normalized;
        if (KeepDistance < targetDifference.magnitude)
        {
            if (Vector3.Angle(targetDir, transform.up) < 90)
            {
                m_Ship.moveForward();
            }
        }
    }

    void requstSupport()
    {
        if (!Target)
            return;

        Ship targetShip = Target.GetComponent<Ship>();
        //  战力差距太大就请求支援
        float fightingCapacity = m_Ship.FightingCapacity;
        var parentObj = transform.parent;
        if (null != parentObj)
        {
            Headquarters headquarters = parentObj.GetComponent<Headquarters>();
            if (headquarters)
            {
                var armShips = headquarters.GetShipsOfArmTarget(Target);
                foreach (var armShipObj in armShips)
                {
                    Ship armShip = armShipObj.GetComponent<Ship>();
                    if (armShip)
                    {
                        fightingCapacity += armShip.FightingCapacity;
                    }
                }
                if (fightingCapacity < targetShip.FightingCapacity)
                {
                    headquarters.SupportMe(Target, gameObject, targetShip.FightingCapacity - fightingCapacity);
                }
            }
        }
    }

    float checkFightingCapacityScale(Ship target)
    {
        float fightingCapacity = 0;
        var parentObj = transform.parent;
        if (null != parentObj)
        {
            Headquarters headquarters = parentObj.GetComponent<Headquarters>();
            if (headquarters)
            {
                var armShips = headquarters.GetShipsOfArmTarget(target.gameObject);
                foreach (var armShipObj in armShips)
                {
                    Ship armShip = armShipObj.GetComponent<Ship>();
                    if (armShip)
                    {
                        fightingCapacity += armShip.FightingCapacity;
                    }
                }
            }
        }
        return fightingCapacity / target.FightingCapacity;
    }

    void checkShip()
    {
        if (null == m_Ship)
            return;
        m_CheckTimeCount += Time.fixedDeltaTime;
        if(m_CheckTimeCount < m_CheckInterval)
        {
            return;
        }
        m_CheckTimeCount = 0;


        float minDistance = -1;
        MinDistance = -1;
        MaxDistance = -1;
        for (int i=0; i< m_Ship.m_WeaponSlots.Count; ++i)
        {
            var weaponSlot = m_Ship.m_WeaponSlots[i];

            if(weaponSlot.m_Weapon != null)
            {
                float shotRange = weaponSlot.m_Weapon.ShutRange;
                if (weaponSlot.m_Weapon as UAV != null)
                    shotRange = 20;
                if (shotRange > MaxDistance || MaxDistance < 0)
                    MaxDistance = shotRange;

                if (shotRange < minDistance || minDistance < 0)
                    minDistance = shotRange;
                if ((weaponSlot.m_Weapon.m_Speciality != Weapon.Speciality.POINT_DEFENSE  && (shotRange < MinDistance || MinDistance < 0)))
                {
                    MinDistance = shotRange;
                }
            }
        }
        if (MinDistance < 0 && minDistance > 0)
            MinDistance = minDistance;


        //  给没有武器的武器槽配备武器
        if (!m_IsManual)
        {
            for (int i = 0; i < m_Ship.m_WeaponSlots.Count; ++i)
            {
                if (m_Ship.m_WeaponSlots[i].m_Weapon != null)
                    continue;
                if (m_Ship.m_WeaponSlots[i].hasFixedWeapon())
                    continue;
                Weapon newWeapon = null;
                if (m_Ship.m_WeaponSlots[i].PerloadWeapon != "")
                    newWeapon = ItemFactory.Instance.createItem(m_Ship.m_WeaponSlots[i].PerloadWeapon) as Weapon;
                else
                    newWeapon = ItemFactory.Instance.createRandomWeaponByLevel(m_Ship.m_WeaponSlots[i].m_Level, m_Ship.m_WeaponSlots[i].m_Speciality, m_Ship.m_ShipStruct.m_ResearchInfluence, m_Ship.m_WeaponSlots[i].m_HasAirplant);
                m_Ship.m_WeaponSlots[i].switchWeapon(newWeapon);
            }
            if (Target)
            {
                m_Ship.ArmShip(Target.GetComponent<Ship>());
            }
        }
    }
}
